package me.aartikov.alligator.destinations;

import me.aartikov.alligator.converters.IntentConverter;
import me.aartikov.alligator.converters.ScreenResultConverter;
import me.aartikov.alligator.AbilityResult;
import me.aartikov.alligator.Screen;
import me.aartikov.alligator.ScreenResult;
import me.aartikov.alligator.helpers.ScreenClassHelper;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.app.Context;


public class AbilityDestination implements Destination {
    private Class<? extends Screen> mScreenClass;

    private Class<? extends Ability> mActivityClass;
    private IntentConverter<? extends Screen> mIntentConverter;


    private Class<? extends ScreenResult> mScreenResultClass;
    private int mRequestCode;

    private ScreenResultConverter<? extends ScreenResult> mScreenResultConverter;

    private ScreenClassHelper mScreenClassHelper;

    public AbilityDestination(Class<? extends Screen> screenClass,
                              Class<? extends Ability> activityClass,
                              IntentConverter<? extends Screen> intentConverter,
                              Class<? extends ScreenResult> screenResultClass,
                              ScreenResultConverter<? extends ScreenResult> screenResultConverter,
                              int requestCode,
                              ScreenClassHelper screenClassHelper) {
        mScreenClass = screenClass;
        mActivityClass = activityClass;
        mIntentConverter = intentConverter;
        mScreenResultClass = screenResultClass;
        mScreenResultConverter = screenResultConverter;
        mRequestCode = requestCode;
        mScreenClassHelper = screenClassHelper;
    }

    public AbilityDestination(Class<? extends Screen> screenClass,
                              Class<? extends Ability> activityClass,
                              IntentConverter<? extends Screen> intentConverter,
                              ScreenClassHelper screenClassHelper) {
        this(screenClass, activityClass, intentConverter, null, null, -1, screenClassHelper);
    }

    @SuppressWarnings("unchecked")

    public Intent createIntent(Context context, Screen screen, Class<? extends Screen> previousScreenClass) {
        checkScreenClass(screen.getClass());
        Intent intent = ((IntentConverter<Screen>) mIntentConverter).createIntent(context,screen);
        mScreenClassHelper.putScreenClass(intent, screen.getClass());
        if (previousScreenClass != null) {
            mScreenClassHelper.putPreviousScreenClass(intent, previousScreenClass);
        }
        return intent;
    }


    public Intent createEmptyIntent(Context context, Class<? extends Screen> screenClass) {
        if (mActivityClass == null) {
            return null;
        }
        Intent intent = ((IntentConverter<Screen>) mIntentConverter).createIntent(context,null);

        mScreenClassHelper.putScreenClass(intent, screenClass);
        return intent;
    }

    @SuppressWarnings("unchecked")

    public AbilityResult createActivityResult(ScreenResult screenResult) {
        checkScreenResultClass(screenResult.getClass());
        if (mScreenResultConverter == null) {
            throw new RuntimeException("mScreenResultConverter is null");
        }
        return ((ScreenResultConverter<ScreenResult>) mScreenResultConverter).createActivityResult(screenResult);
    }


    public Screen getScreen(Ability activity) {
        return mIntentConverter.getScreen(activity.getIntent());
    }


    public Class<? extends ScreenResult> getScreenResultClass() {
        return mScreenResultClass;
    }

    public int getRequestCode() {
        return mRequestCode;
    }

    @SuppressWarnings("unchecked")

    public ScreenResult getScreenResult(AbilityResult activityResult) {
        if (mScreenResultConverter == null) {
            throw new RuntimeException("mScreenResultConverter is null");
        }
        return ((ScreenResultConverter<ScreenResult>) mScreenResultConverter).getScreenResult(activityResult);
    }

    private void checkScreenClass(Class<? extends Screen> screenClass) {
        if (!mScreenClass.isAssignableFrom(screenClass)) {
            throw new IllegalArgumentException("Invalid screen class " + screenClass.getSimpleName() + ". Expected " + mScreenClass.getSimpleName());
        }
    }

    private void checkScreenResultClass(Class<? extends ScreenResult> screenResultClass) {
        if (mScreenResultClass == null) {
            throw new RuntimeException("mScreenResultClass is null");
        }
        if (!mScreenResultClass.isAssignableFrom(screenResultClass)) {
            throw new IllegalArgumentException("Invalid screen result class " + screenResultClass.getCanonicalName() + ". Expected " + mScreenResultClass.getCanonicalName());
        }
    }
}
